﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;

using AutoMapper;

using Opentao.NotificationService.Application.Service.DTO;
using Opentao.NotificationService.Business.Objects;
using Opentao.NotificationService.Common.Data.Entities;

namespace Opentao.NotificationService.Application.Service
{
    /// <summary>
    /// Админский интерфейс для работы с сервисом оповещений.
    /// </summary>
    public class AdminService : IAdminService, IDisposable
    {
        #region Private Fields
        private readonly RecipientBO _recipientBO = new Lazy<RecipientBO>().Value;

        private readonly ImportanceLevelBO _importanceLevelBO = new Lazy<ImportanceLevelBO>().Value;

        private readonly EventTypeBO _eventTypeBO = new Lazy<EventTypeBO>().Value;
        #endregion




        #region Constructors
        public AdminService()
        {
            //Mapper.CreateMap<EntityBase, RecipientDTO>().Include<Recipient, RecipientDTO>().ForMember(r => r.Id, m=> m.MapFrom(e => e.Id));
            Mapper.CreateMap<Recipient, RecipientDTO>();
            Mapper.CreateMap<ImportanceLevel, ImportanceLevelDTO>();
            Mapper.CreateMap<EventType, EventTypeDTO>();
        }
        #endregion




        #region Recipients Methods
        /// <summary>
        /// Создать нового получателя.
        /// </summary>
        /// <param name="email"> Адрес электронной почты получателя. </param>
        /// <param name="phone"> Номер телефона получателя. </param>
        /// <param name="name"> Имя получателя. </param>
        public void CreateRecipient(
            string email,
            string phone,
            string name )
        {
            _recipientBO.CreateRecipients(
                new List<Recipient> {
                                        new Recipient {
                                                          Email = email,
                                                          Phone = phone,
                                                          Name = name
                                                      }
                                    } );
        }

        /// <summary>
        /// Выдать получателя с указанным id.
        /// </summary>
        /// <param name="id"> Id получателя. </param>
        /// <returns> Получатель с указанным id или null, если получателя с таким id нет. </returns>
        public RecipientDTO GetRecipient( int id )
        {
            return Mapper.Map<Recipient, RecipientDTO>( _recipientBO.GetRecipient( id ) );
        }

        /// <summary>
        /// Выдать получателей постранично.
        /// C значением параметра recordsPerPage меньше 1 - выдать все записи.
        /// Нумерация страниц начинается с нуля.
        /// </summary>
        /// <param name="isSortOrderAscending"> Направление сортировки. </param>
        /// <param name="sortProperty"> Имя свойства, по которому нужно отсортировать записи. </param>
        /// <param name="recordsPerPage"> Количество записей на одну страницу. </param>
        /// <param name="pageNumber"> Номер страницы. </param>
        /// <returns> Список получателей. </returns>
        public List<RecipientDTO> GetRecipients(
            bool isSortOrderAscending,
            string sortProperty,
            int recordsPerPage,
            int pageNumber )
        {
            return Mapper.Map<List<Recipient>, List<RecipientDTO>>(
                _recipientBO.GetRecipients(
                    isSortOrderAscending
                        ? SortOrder.Ascending
                        : SortOrder.Descending,
                    sortProperty,
                    recordsPerPage,
                    pageNumber ).ToList() );
        }

        /// <summary>
        /// Выдать количество всех записей о получателях.
        /// </summary>
        /// <returns> Количество записей о получателях. </returns>
        public int GetRecipientsCount()
        {
            return _recipientBO.GetRecipientsCount();
        }

        /// <summary>
        /// Обновить данные получателя.
        /// </summary>
        /// <param name="id"> Id получателя, чьи данные необходимо обновить. </param>
        /// <param name="email"> Обновлённый e-mail получателя. </param>
        /// <param name="phone"> Обновлённый номер телефона получателя. </param>
        /// <param name="name"> Обновлённое имя получателя. </param>
        public void UpdateRecipient(
            int id,
            string email,
            string phone,
            string name )
        {
            _recipientBO.UpdateRecipients(
                new List<Recipient> {
                                        new Recipient {
                                                          Id = id,
                                                          Email = email,
                                                          Phone = phone,
                                                          Name = name
                                                      }
                                    } );
        }

        /// <summary>
        /// Удалить получателя.
        /// </summary>
        /// <param name="id"> Id получателя, которого необходимо удалить. </param>
        public void DeleteRecipient( int id )
        {
            _recipientBO.DeleteRecipients(
                new List<int> {
                                  id
                              } );
        }

        /// <summary>
        /// Подписать получателя на тип событий.
        /// </summary>
        /// <param name="recipientId"> Id получателя. </param>
        /// <param name="eventTypeId"> Id типа событий. </param>
        public void SubscribeRecipient(
            int recipientId,
            int eventTypeId )
        {
            _recipientBO.SubscribeRecipients(
                new List<int> {
                                  recipientId
                              },
                new List<int> {
                                  eventTypeId
                              } );
        }

        /// <summary>
        /// Отписать получателя от типа событий.
        /// </summary>
        /// <param name="recipientId"> Id получателя. </param>
        /// <param name="eventTypeId"> Id тип событий. </param>
        public void UnSubscribeRecipient(
            int recipientId,
            int eventTypeId )
        {
            _recipientBO.UnsubscribeRecipients(
                new List<int> {
                                  recipientId
                              },
                new List<int> {
                                  eventTypeId
                              } );
        }
        #endregion




        #region ImportanceLevels Methods
        /// <summary>
        /// Создать уровень важности.
        /// </summary>
        /// <param name="title"> Название уровня важности. </param>
        /// <param name="useEmail"> Определяет, использовать ли email в рассылке с этим уровнем важности. </param>
        /// <param name="usePhone"> Определяет, использовать ли SMS в рассылке с этим уровнем важности. </param>
        public void CreateImportanceLevel(
            string title,
            bool useEmail,
            bool usePhone )
        {
            _importanceLevelBO.CreateImportanceLevels(
                new List<ImportanceLevel> {
                                              new ImportanceLevel {
                                                                      Title = title,
                                                                      UseEmail = useEmail,
                                                                      UsePhone = usePhone
                                                                  }
                                          } );
        }

        /// <summary>
        /// Выдать уровни важности.
        /// </summary>
        /// <returns> Список уровней важности. </returns>
        public List<ImportanceLevelDTO> GetImportanceLevels()
        {
            return
                Mapper.Map<List<ImportanceLevel>, List<ImportanceLevelDTO>>(
                    _importanceLevelBO.GetImportanceLevels().ToList() );
        }

        /// <summary>
        /// Обновить уровень важности.
        /// </summary>
        /// <param name="id"> Id уровня важности. </param>
        /// <param name="title"> Обновленное название уровня важности. </param>
        /// <param name="useEmail"> Обновлённое "использовать e-mail в рассылке с этим уровнем важности. </param>
        /// <param name="usePhone"> Обновлённое "использовать SMS в рассылке с этим уровнем важности. </param>
        public void UpdateImportanceLevel(
            int id,
            string title,
            bool useEmail,
            bool usePhone )
        {
            _importanceLevelBO.UpdateImportanceLevels(
                new List<ImportanceLevel> {
                                              new ImportanceLevel {
                                                                      Id = id,
                                                                      Title = title,
                                                                      UseEmail = useEmail,
                                                                      UsePhone = usePhone
                                                                  }
                                          } );
        }

        /// <summary>
        /// Удалить уровень важности по Id.
        /// </summary>
        /// <param name="id"> Id уровня важности. </param>
        public void DeleteImportanceLevel( int id )
        {
            _importanceLevelBO.DeleteImportanceLevels(
                new List<int> {
                                  id
                              } );
        }
        #endregion




        #region EventTypes Methods
        /// <summary>
        /// Создать тип событий.
        /// </summary>
        /// <param name="title"> Название типа событий. </param>
        public void CreateEventType( string title )
        {
            _eventTypeBO.CreateEventTypes(
                new List<EventType> {
                                        new EventType {
                                                          Title = title
                                                      }
                                    } );
        }

        /// <summary>
        /// Выдать типы событий.
        /// </summary>
        /// <returns> Список типов событий. </returns>
        public List<EventTypeDTO> GetEventTypes()
        {
            return Mapper.Map<List<EventType>, List<EventTypeDTO>>( _eventTypeBO.GetEventTypes().ToList() );
        }

        /// <summary>
        /// Обновить тип событий.
        /// </summary>
        /// <param name="id"> Id типа событий, который необходимо обновить. </param>
        /// <param name="title"> Обновлённое имя типа событий. </param>
        public void UpdateEventType(
            int id,
            string title )
        {
            _eventTypeBO.UpdateEventTypes(
                new List<EventType> {
                                        new EventType {
                                                          Id = id,
                                                          Title = title,
                                                      }
                                    } );
        }

        /// <summary>
        /// Удалить тип событий по Id.
        /// </summary>
        /// <param name="id"> Id типа событий, который необходимо удалить. </param>
        public void DeleteEventType( int id )
        {
            _eventTypeBO.DeleteEventTypes(
                new List<int> {
                                  id
                              } );
        }
        #endregion




        #region Implementation of IDisposable
        /// <summary>
        /// Освободить все занятые ресурсы.
        /// </summary>
        public void Dispose()
        {
            _recipientBO.Dispose();
            _importanceLevelBO.Dispose();
            _eventTypeBO.Dispose();
        }
        #endregion
    }
}